package com.shuwei.location.wificollect;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiManager;
import android.os.Handler;

import com.shuwei.location.permission.Permissions;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author Halohoop
 *         Created by Halohoop on 2017/10/31.
 */

public class WifiCollector<T> {

    public final static int TYPE_FAIL_WIFI_SWITCH_OFF = 0;
    public final static int TYPE_FAIL_WIFI_ERROR_OCCUR = 1;

    private final Context context;
    private WifiManager wifiManager;
    private StateReceiver stateReceiver;
    private WifiCollectListener<T> wifiCollectListener;
    private Converter<T> converter;

    private Config config;

    private WifiCollector(Context context, Config config, WifiCollectListener<T> wifiCollectListener,
                          Converter<T> converter) {
        this.context = context;
        this.config = config;
        this.wifiCollectListener = wifiCollectListener;
        this.converter = converter;
        this.wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context
                .WIFI_SERVICE);
    }

    private boolean isCollecting = false;

    public boolean isCollecting() {
        return isCollecting;
    }

    /**
     * 对消息，扫描结果，网络状态的广播接收和处理
     */
    private class StateReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action == null) {
                return;
            }
            switch (action) {
                case WifiManager.SCAN_RESULTS_AVAILABLE_ACTION:
                    isCollecting = false;
                    if (wifiCollectListener != null) {
                        if (Permissions.permissionsCheck(context,
                                new String[]{Manifest.permission.ACCESS_FINE_LOCATION,
                                        Manifest.permission.ACCESS_COARSE_LOCATION})) {
                            List<ScanResult> scanResults = wifiManager.getScanResults();
                            List<T> ts = sortAndFilterByMultiCondition(scanResults);
                            if (ts == null) {
                                ts = Collections.emptyList();
                            }
                            WifiCollector.this.wifiCollectListener.wifiCollectSuccess(ts);
                        } else {//对于有些手机没有权限也可以获取列表的手机，没有注册这项的权限
                            try {
                                List<ScanResult> scanResults = wifiManager.getScanResults();
                                List<T> ts = sortAndFilterByMultiCondition(scanResults);
                                if (ts == null) {
                                    ts = Collections.emptyList();
                                }
                                WifiCollector.this.wifiCollectListener.wifiCollectSuccess(ts);
                            } catch (Exception e) {//可能由于权限拒绝
                                e.printStackTrace();
                                wifiCollectListener.wifiCollectFail(
                                        WifiCollector.TYPE_FAIL_WIFI_ERROR_OCCUR,
                                        e.getMessage());
                            }
                        }
                    }
                    context.unregisterReceiver(stateReceiver);
                    break;
                default:
                    break;
            }
        }
    }

    /**
     * 排序，删减，并且，过滤
     * @param scanResults
     * @return
     */
    private List<T> sortAndFilterByMultiCondition(List<ScanResult> scanResults) {
        List<T> scanResultFilters = null;
        final int size = scanResults.size();
        if (scanResults != null && size > 0) {
            //先排序在进行数量限制
            final int sortTarget = WifiCollector.this.config.sortTarget;
            //冒泡
            List<ScanResult> toBeSortedList = new ArrayList<>(scanResults.size());
            toBeSortedList.addAll(scanResults);
            if (WifiCollector.this.config.sortType != Config.SORT_TYPE_NO_SORT) {
                Collections.sort(toBeSortedList, new Comparator<ScanResult>() {
                    //如果返回时负数两个就会被交换
                    @Override
                    public int compare(ScanResult o1, ScanResult o2) {
                        final boolean sortTypeAToZ0To9WeakToStrong =
                                WifiCollector.this.config.sortType == Config.SORT_TYPE_A2Z_0TO9_WEAKTOSTRONG;
                        int i;
                        switch (sortTarget) {
                            case Config.SORT_TARGET_SSID:
                                //String的compareTo<0   abc..
                                //String的compareTo>0   ..cba
                                i = o1.SSID.compareTo(o2.SSID);
                                break;
                            case Config.SORT_TARGET_BSSID:
                                i = o1.BSSID.toUpperCase().compareTo(o2.BSSID.toUpperCase());
                                break;
                            case Config.SORT_TARGET_RSSI:
                            default:
                                i = WifiManager.compareSignalLevel(o1.level, o2.level);
                                break;
                        }
                        if (i < 0) {
                            //左a    右b
                            //左weak 右strong
                            return sortTypeAToZ0To9WeakToStrong ? -1 : 1;
                        } else if(i > 0) {
                            //左b        右a
                            //左strong   右weak
                            return sortTypeAToZ0To9WeakToStrong ? 1 : -1;
                        } else {
                            return i;
                        }
                    }
                });
            }
            int sizeNeed;
            if(WifiCollector.this.config.count == Config.COUNT_UNLIMITED ) {
                sizeNeed = size;
            } else {
                sizeNeed = Math.min(WifiCollector.this.config.count, size);
            }
            scanResultFilters = new ArrayList<>(sizeNeed);
            for (int i = 0; i < sizeNeed; i++) {
                ScanResult scanResult = toBeSortedList.get(i);
                boolean isNeedIgnore = filtersIgnore(scanResult);
                if (!isNeedIgnore) {
                    if (WifiCollector.this.config.isRemoveMacColon) {
                        scanResult.BSSID = scanResult.BSSID.replace(":", "");
                    }
                    scanResultFilters.add(WifiCollector.this.converter.convert(scanResult));
                }
            }
            return scanResultFilters;
        }
        return scanResultFilters;
    }

    /**
     * 过滤器，每个信号都需要经过这个方法,batch
     * @param scanResult
     * @return 是否需要忽略这个信号
     */
    private boolean filtersIgnore(ScanResult scanResult) {
        boolean isNeedIgnore = false;
        if (WifiCollector.this.config.filterIgnoreBSSIDs != null
                && WifiCollector.this.config.filterIgnoreBSSIDs.length > 0) {
            //mac地址过滤
            for (int j = 0;
                 j < WifiCollector.this.config.filterIgnoreBSSIDs
                         .length;
                 j++) {
                if (scanResult.BSSID.equalsIgnoreCase(WifiCollector
                        .this.config
                        .filterIgnoreBSSIDs[j])) {
                    isNeedIgnore = true;
                }
            }
        }
        if (isNeedIgnore) {
            return isNeedIgnore;
        }

        if (WifiCollector.this.config.filterIgnoreSSIDs != null
                && WifiCollector.this.config.filterIgnoreSSIDs.length > 0) {
            //wifi名称过滤
            for (int j = 0;
                 j < WifiCollector.this.config.filterIgnoreSSIDs
                         .length;
                 j++) {
                if (scanResult.SSID.equals(WifiCollector.this.config
                        .filterIgnoreSSIDs[j])) {
                    isNeedIgnore = true;
                }
            }
            if (isNeedIgnore) {
                return isNeedIgnore;
            }
        }

        //wifi信号强度过滤
        final int filterRssi = WifiCollector.this.config.filterRssi;
        if (filterRssi != Config.FILTERRSSI_UNLIMITED) {
            final int level = scanResult.level;
            /*
            * Returns <0 if the first signal is weaker than the
            * second signal,
            * 0 if the two signals have the same strength, and >0
             * if the first
            * signal is stronger than the second signal.
            * */
            final int compareResult = WifiManager.compareSignalLevel(level, filterRssi);
            if (compareResult < 0) {
                isNeedIgnore = true;
            }
        }
        return isNeedIgnore;
    }

    /**
     * 默认只需要最强的15个
     */
//    private final static int SIZE = 15;
    /**
     * 默认只需要强度大于-80的
     */
//    private final static int RSSI = -80;

    /**
     * 开始手机
     *
     * @param handler
     */
    public void collect(Handler handler) {
        if (!isCollecting) {
            if (stateReceiver == null) {
                stateReceiver = new StateReceiver();
            }
            IntentFilter intentFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
            context.registerReceiver(stateReceiver, intentFilter, null, handler);
            if (!wifiManager.isWifiEnabled()) {
                if (wifiCollectListener != null) {
                    wifiCollectListener.wifiCollectFail(
                            WifiCollector.TYPE_FAIL_WIFI_SWITCH_OFF, "请开启Wifi开关！");
                }
                //TODO 暂时不自动开启Wifi
//                wifiManager.setWifiEnabled(true);
                return;
            }
            isCollecting = wifiManager.startScan();
            if (!isCollecting) {
                if (wifiCollectListener != null) {
                    wifiCollectListener.wifiCollectFail(
                            WifiCollector.TYPE_FAIL_WIFI_ERROR_OCCUR, "Wifi开启扫描失败！");
                }
            }
        }
    }

    public static class Config {
        /**
         * 数量
         */
        public static final int COUNT_UNLIMITED = -1;
        private int count = COUNT_UNLIMITED;

        /**
         * 排序方式
         */
        public static final int SORT_TYPE_NO_SORT = 0;
        public static final int SORT_TYPE_A2Z_0TO9_WEAKTOSTRONG = 1;
        public static final int SORT_TYPE_Z2A_9TO0_STRONGTOWEAK = 2;
        /**
         * 默认不排序
         */
        private int sortType = SORT_TYPE_NO_SORT;

        /**
         * 按照什么排序
         * 强度
         */
        public static final int SORT_TARGET_RSSI = 0;
        /**
         * mac地址  abc..xyz/zyx..cba
         */
        public static final int SORT_TARGET_BSSID = 1;
        /**
         * wifi名字  abc..xyz/zyx..cba
         */
        public static final int SORT_TARGET_SSID = 2;
        private int sortTarget = SORT_TARGET_RSSI;

        /**
         * 需要忽略的mac地址
         */
        private String[] filterIgnoreBSSIDs = null;
        /**
         * 需要忽略的wifi名字
         */
        private String[] filterIgnoreSSIDs = null;

        /**
         * 信号强度小于多少就丢弃
         * -1标识不丢弃
         */
        public static final int FILTERRSSI_UNLIMITED = -1;
        private int filterRssi = FILTERRSSI_UNLIMITED;

        /**
         * 是否需要把mac地址的冒号去掉，默认不许掉
         */
        private boolean isRemoveMacColon = false;

        public void setFilterIgnoreBSSIDs(String[] filterIgnoreBSSIDs) {
            this.filterIgnoreBSSIDs = filterIgnoreBSSIDs;
        }

        public void setFilterIgnoreSSIDs(String[] filterIgnoreSSIDs) {
            this.filterIgnoreSSIDs = filterIgnoreSSIDs;
        }

        private Config() {
        }
    }

    /**
     * bean的重新转换，比如把ScanResult转换成WifiItem
     * @param <T>
     */
    public interface Converter<T> {
        T convert(ScanResult scanResult);
    }

    public static class Builder<T> {
        private Context context;
        private Config config;
        private WifiCollectListener<T> wifiCollectListener;
        private Converter<T> converter;

        public Builder(Context context) {
            this.context = context;
        }

        private void createConfigIfNeeded() {
            if (config == null) {
                config = new Config();
            }
        }

        public Builder<T> setCount(int count) {
            createConfigIfNeeded();
            this.config.count = count;
            return this;
        }

        public Builder<T> setSortType(int sortType) {
            createConfigIfNeeded();
            this.config.sortType = sortType;
            return this;
        }

        public Builder<T> setSortTarget(int sortTarget) {
            createConfigIfNeeded();
            this.config.sortTarget = sortTarget;
            return this;
        }

        public Builder<T> setIgnoreBSSIDs(String[] ignoreBSSIDs) {
            createConfigIfNeeded();
            this.config.filterIgnoreBSSIDs = ignoreBSSIDs;
            return this;
        }

        public Builder<T> setIgnoreSSIDs(String[] ignoreSSIDs) {
            createConfigIfNeeded();
            this.config.filterIgnoreSSIDs = ignoreSSIDs;
            return this;
        }

        public Builder<T> setIsRemoveMacColon(boolean isRemoveMacColon) {
            this.config.isRemoveMacColon = isRemoveMacColon;
            return this;
        }

        /**
         * 必须要调用的
         * @param wifiCollectListener
         * @return
         */
        public Builder<T> setWifiCollectListener(WifiCollectListener<T> wifiCollectListener) {
            this.wifiCollectListener = wifiCollectListener;
            return this;
        }

        /**
         * 必须要调用的
         * @param converter
         * @return
         */
        public Builder<T> setConverter(Converter<T> converter) {
            this.converter = converter;
            return this;
        }

        public WifiCollector<T> create() {
            createConfigIfNeeded();
            if (this.wifiCollectListener == null) {
                throw new RuntimeException("请传入回调");
            }
            if (this.converter == null) {
                throw new RuntimeException("请非空converter实例");
            }
            return new WifiCollector<T>(
                    this.context,
                    this.config,
                    this.wifiCollectListener,
                    this.converter);
        }
    }
}
